package com.mostka.wsrpc.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.mostka.rpc.client.CloseHandler;
import com.mostka.rpc.client.WebSocketRpc;
import com.mostka.rpc.client.WsRpcOnStateHandler;
import com.mostka.wsrpc.client.ui.ChoseChannelHandler;
import com.mostka.wsrpc.client.ui.DisconnectHandler;
import com.mostka.wsrpc.client.ui.MainWindow;
import com.mostka.wsrpc.client.ui.MessageSendHandler;
import com.mostka.wsrpc.client.ui.MessengerSelectHandler;
import com.mostka.wsrpc.shared.Channels;
import com.mostka.wsrpc.shared.Messenger;
import java.util.HashMap;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class GwtWsRpcChat implements EntryPoint, MessageSendHandler, MessengerSelectHandler, WsRpcOnStateHandler, ChoseChannelHandler, DisconnectHandler {

    private static int TO_ALL = -2;
    private static int SELF_ID = -1;

    MainWindow mainWindow = new MainWindow();
    private Messenger messengerSelf;
    private final TestWsServerAsync server = GWT.create(TestWsServer.class);
    private HashMap<Integer ,Messenger> messengers = new HashMap<Integer ,Messenger>();
    private String nick;
    int recipientId = TO_ALL;
    WebSocketRpc webSocket;
    private boolean disconnectClicked = false;

    public void onModuleLoad() {
    	
    	GWT.create(Messenger.class);
    	
		if (!WebSocketRpc.isSupported()){
			Window.alert("Web socket is not suported");
		}
		// create web socket rpc manager
        webSocket = new WebSocketRpc();

        nick = MainWindow.getNick();
        messengerSelf = new Messenger(SELF_ID,"me");
        
        // init messages board
        mainWindow.addSendHandler(this);
        mainWindow.addMessengerSelectHandler(this);
        mainWindow.setChoseChannelHandler(this);
        mainWindow.setDisconnectClickHandler(this);
        mainWindow.setRecipient("All");
        
        mainWindow.showJoinForm();

    }

    // when user select join button
	public void onChannelChose(final String channelName) {
    	final WsRpcOnStateHandler stateHandler = this;
    	webSocket.close(server, client, new CloseHandler() {
			public void onClose() {
				RootPanel.get().clear();
		    	RootPanel.get().add(new HTML("connecting..."));
		    	// create web socket connection with connection status handler
		        webSocket.join(channelName, server,client,stateHandler);
			}
		});
        
    }
    // ============= Connection handlers ============== //
    public void onError(String data) {
        Window.alert("some is wrong");
    }

    @Override
    public void onClose(int code, String message) {
    	if (disconnectClicked==false){
    		Window.alert("socked is closed: "+message);
    	}
    	disconnectClicked=false;
        RootPanel.get().clear();
        mainWindow.showJoinForm();
    }

    @Override
    public void onJoin() {
        RootPanel.get().clear();
        mainWindow.clearBoard();
        mainWindow.addMessenger(TO_ALL,"All",Channels.DEFAULT_AVATAR);
        RootPanel.get().add(mainWindow);
        
        // send user nick to server
        server.join(nick);
        // ask server for all connected users. server will call back client.messengersRetrieved(users)
        server.getMessengers();
    }
    // ============= Client handler ============== //
    // handle messages from server
    private TestWsClient client = new TestWsClient() {
    	// new messages retrieved
        public void onMessage(int senderId, String message) {
        	Messenger sender = messengers.get(senderId);
        	if (sender!=null) {
        		mainWindow.addMessage(sender.getId(), sender.getNick() ,message);
			}
        }
        // new user joined
        public void onMessengerJoin(Messenger messenger) {
            messengers.put(messenger.getId(), messenger);
            mainWindow.addMessenger(messenger.getId(),messenger.getNick(),messenger.getAvatarPath());
        }
        // some user disconect
        public void onMessengerDisconnect(int messengerId) {
            messengers.remove(messengerId);
            mainWindow.removeMessenger(messengerId);
        }
        // retrieved users 
		public void messengersRetrieved(Messenger[] newMessengers) {
			for (Messenger messenger : newMessengers) {
	            messengers.put(messenger.getId(), messenger);
	            mainWindow.addMessenger(messenger.getId(), messenger.getNick(), messenger.getAvatarPath());
			}
		}
    };
    // ============= Chat board handlers ===================//
    public void onMessageSend(String message) {
        mainWindow.addMessage(messengerSelf.getId(),messengerSelf.getNick(),message);
        if (recipientId==TO_ALL){
        	// send message to all
            server.sendToAll(message);
        }else{
        	// send message to defined user
            server.sendTo(recipientId,message);
        }
    }
    @Override
    public void onMessengerSelect(int userId) {
        if (userId != SELF_ID) {
        	if (userId==TO_ALL){
	    		mainWindow.setRecipient("All");
	    		recipientId = userId;
        	}else{
		    	Messenger recipient = messengers.get(userId);
		    	if (recipient!=null) {
		    		mainWindow.setRecipient(recipient.getNick());
		    		recipientId = userId;
				}
        	}
        }
    }

	@Override
	public void onDisconnectClick() {
		disconnectClicked=true;
		// close web socket connection
		webSocket.close(server, client);
        RootPanel.get().clear();
        mainWindow.showJoinForm();
	}
}
